package org.idea.qiyu.framework.datasource.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.idea.qiyu.framework.datasource.config.DataSourceContextHolder;
import org.idea.qiyu.framework.datasource.properties.MultiPackageDatasourceProperties;
import org.springframework.aop.support.AopUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;

/**
 * 多包管理数据源 切面
 *
 * @Author linhao
 * @Date created in 4:48 下午 2021/5/25
 */
@Aspect
@Component
@ConditionalOnProperty(name = "multi.package.isOpen", havingValue = "true")
@Order(1)
public class MultiPackageDatasourceAspect {

    @Resource
    private MultiPackageDatasourceProperties multiPackageDatasourceProperties;

    @Pointcut("execution(* org.idea..*Dao.*(..))")
    public void daoPackagePointCut() {
    }

    @Pointcut("execution(* org.idea..*Mapper.*(..))")
    public void mapperPackagePointCut() {
    }

    @Before("daoPackagePointCut() || mapperPackagePointCut()")
    public void before(JoinPoint joinPoint) {
        Map<String, String> map = multiPackageDatasourceProperties.getDatasources();
        if (map == null || map.size() < 1) {
            return;
        }
        Class clazz = ((Class) AopUtils.getTargetClass(joinPoint.getTarget()).getGenericInterfaces()[0]);
        if (clazz == null) {
            return;
        }
        String childPackageName = clazz.getName().substring(0, clazz.getName().lastIndexOf("."));
        if (childPackageName != null && childPackageName != "") {
            for (String packageName : map.keySet()) {
                //考虑到包目录下边可能还会分包，这里用模糊匹配
                if (childPackageName.contains(packageName)) {
                    String dataSource = map.get(packageName);
                    DataSourceContextHolder.setDatasource(dataSource);
                    return;
                }
            }
        }
    }

    @After("daoPackagePointCut() || mapperPackagePointCut()")
    public void doAfter() {
        DataSourceContextHolder.clearDatasource();
    }
}
